
function g2kml() { };

g2kml.prototype.getOverlayKmlGeometryString = function (overlay) {
    if (!overlay)
        return '';

    if (this.isArray(overlay)) {
        var result = '';
        var len = overlay.length;
        for (var i = 0; i < len; i++) {
            result = result + this.getOverlayKmlGeometryString(overlay[i]);
        }
        return "<MultiGeometry>" + result + "</MultiGeometry>";
    }

    if (overlay instanceof google.maps.Marker)
        return this.getPointKmlGeometryString(overlay.getPosition());
    else if (overlay instanceof google.maps.Polyline)
        return this.getLineKmlGeometryString(overlay.getPath());
    else if (overlay instanceof google.maps.Polygon)
        return this.getPolygonKmlGeometryString(overlay.getPaths());

    throw 'Invalid argument specified';
};

g2kml.prototype.getLineKmlGeometryString = function (path) {
    if (!path)
        return '';

    return "<LineString><coordinates>" + this.getPathKmlGeometryString.apply(this, arguments) + "</coordinates></LineString>";
};

g2kml.prototype.getPolygonKmlGeometryString = function (rings) {
    if (!rings)
        return '';

    var outerPrefix = "<outerBoundaryIs><LinearRing><coordinates>";
    var outerSuffix = "</coordinates></LinearRing></outerBoundaryIs>";
    var innerPrefix = "<innerBoundaryIs><LinearRing><coordinates>";
    var innerSuffix = "</coordinates></LinearRing></innerBoundaryIs>";
    var result = '';
    if (this.isArray(rings)) {
        var len = rings.length;
        for (var i = 0; i < len; i++) {
            if (!i)
                result = outerPrefix + this.getPathKmlGeometryString(rings[i]) + outerSuffix;
            else
                result = result + innerPrefix + this.getPathKmlGeometryString(rings[i]) + innerSuffix;
        }
        return "<Polygon>" + result + "</Polygon>";
    }

    if (rings instanceof google.maps.MVCArray) {
        var len = rings.getLength();
        for (var i = 0; i < len; i++) {
            if (!i)
                result = outerPrefix + this.getPathKmlGeometryString(rings.getAt(i)) + outerSuffix;
            else
                result = result + innerPrefix + this.getPathKmlGeometryString(rings.getAt(i)) + innerSuffix;
        }
        return "<Polygon>" + result + "</Polygon>";
    }

    throw 'Invalid argument specified';
};

g2kml.prototype.getPointKmlGeometryString = function (latlng) {
    if (!latlng)
        return '';
    return '<Point><coordinates>' + this.getCoordinateString.apply(this, arguments) + '</coordinates></Point>';
};

g2kml.prototype.getPathKmlGeometryString = function (path) {
    if (!path)
        return '';

    var coordinates = '';
    if (this.isArray(path)) {
        var len = path.length;
        var first = true;
        for (var i = 0; i < len; i++) {
            if (first) {
                coordinates = this.getCoordinateString(path[i]);
                first = false;
            }
            else
                coordinates = coordinates + " " + this.getCoordinateString(path[i]);
        }
        return coordinates;
    }

    if (path instanceof google.maps.MVCArray) {
        var len = path.getLength();
        var first = true;
        for (var i = 0; i < len; i++) {
            if (first) {
                coordinates = this.getCoordinateString(path.getAt(i));
                first = false;
            }
            else
                coordinates = coordinates + " " + this.getCoordinateString(path.getAt(i));
        }
        return coordinates;
    }

    throw 'Invalid argument specified'
};

g2kml.prototype.getCoordinateString = function (latlng) {
    if (!latlng)
        return '';

    var lat = 0, lng = 0, alt = 0;
    if (arguments.length === 1) {
        if (this.isArray(latlng)) {
            if (!(latlng.length === 2 || latlng.length === 3))
                throw 'The argument array should only contain 2 or 3 items corresponding to the "latitude", "longitude" and the optional "altitude" values';
            lat = latlng[0];
            lng = latlng[1];
            if (latlng.length === 3)
                alt = latlng[2];
        }
        else if (latlng instanceof google.maps.LatLng) {
            lat = latlng.lat();
            lng = latlng.lng();
        }
        else
            throw 'Invalid argument specified'
    }
    else if (arguments.length === 2 || arguments.length === 3) {
        lat = arguments[0];
        lng = arguments[1];
        if (arguments.length === 3)
            alt = arguments[2];
    }
    else
        throw 'Too many arguments specified'

    var result = lng + ',' + lat;
    if (alt != 0)
        result = result + ',' + alt;
    return result;
};

g2kml.prototype.isArray = function (obj) {
    return obj.constructor == Array;
};